g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == ot_gio_checksum_stream_async);
return g_memdup (g_simple_async_result_get_op_res_gpointer (simple), 32);
+}
+/**
+ * ot_gio_shutil_cp_al_or_fallback:
+ * @src: Source path
+ * @dest: Destination path
+ * @cancellable:
+ * @error:
+ *
+ * Recursively copy path @src (which must be a directory) to the
+ * target @dest. If possible, hardlinks are used; if a hardlink is
+ * not possible, a regular copy is created. Any existing files are
+ * overwritten.
+ *
+ * Returns: %TRUE on success
+ */
+gboolean
+ot_gio_shutil_cp_al_or_fallback (GFile *src,
+ GFile *dest,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gboolean ret = FALSE;
+ ot_lobj GFileEnumerator *enumerator = NULL;
+ ot_lobj GFileInfo *file_info = NULL;
+ GError *temp_error = NULL;
+
+ enumerator = g_file_enumerate_children (src, OSTREE_GIO_FAST_QUERYINFO,
+ G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+ cancellable, error);
+ if (!enumerator)
+ goto out;
+
+ if (!ot_gfile_ensure_directory (dest, FALSE, error))
+ goto out;
+
+ while ((file_info = g_file_enumerator_next_file (enumerator, cancellable, &temp_error)) != NULL)
+ {
+ const char *name = g_file_info_get_name (file_info);
+ ot_lobj GFile *src_child = g_file_get_child (src, name);
+ ot_lobj GFile *dest_child = g_file_get_child (dest, name);
+
+ if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_DIRECTORY)
+ {
+ if (!ot_gfile_ensure_directory (dest_child, FALSE, error))
+ goto out;
+
+ /* Can't do this even though we'd like to; it fails with an error about
+ * setting standard::type not being supported =/
+ *
+ if (!g_file_set_attributes_from_info (dest_child, file_info, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+ cancellable, error))
+ goto out;
+ */
+ if (chmod (ot_gfile_get_path_cached (dest_child),
+ g_file_info_get_attribute_uint32 (file_info, "unix::mode")) == -1)
+ {
+ ot_util_set_error_from_errno (error, errno);
+ goto out;
+ }
+
+ if (!ot_gio_shutil_cp_al_or_fallback (src_child, dest_child, cancellable, error))
+ goto out;
+ }
+ else
+ {
+ (void) unlink (ot_gfile_get_path_cached (dest_child));
+ if (link (ot_gfile_get_path_cached (src_child), ot_gfile_get_path_cached (dest_child)) == -1)
+ {
+ if (!(errno == EMLINK || errno == EXDEV))
+ {
+ ot_util_set_error_from_errno (error, errno);
+ goto out;
+ }
+ if (!g_file_copy (src_child, dest_child,
+ G_FILE_COPY_OVERWRITE | G_FILE_COPY_ALL_METADATA | G_FILE_COPY_NOFOLLOW_SYMLINKS,
+ cancellable, NULL, NULL, error))
+ goto out;
+ }
+ }
+ g_clear_object (&file_info);
+ }
+ if (temp_error)
+ {
+ g_propagate_error (error, temp_error);
+ goto out;
+ }
+
+ ret = TRUE;
+ out:
+ return ret;
}
+
OstreeRepo *repo;
} OtAdminDeploy;
-static gboolean opt_checkout_only;
+static gboolean opt_no_initramfs;
+static gboolean opt_no_bootloader;
static char *opt_ostree_dir;
static GOptionEntry options[] = {
{ "ostree-dir", 0, 0, G_OPTION_ARG_STRING, &opt_ostree_dir, "Path to OSTree root directory", NULL },
- { "checkout-only", 0, 0, G_OPTION_ARG_NONE, &opt_checkout_only, "Don't generate initramfs or update bootloader", NULL },
+ { "no-initramfs", 0, 0, G_OPTION_ARG_NONE, &opt_no_initramfs, "Don't generate initramfs", NULL },
+ { "no-bootloader", 0, 0, G_OPTION_ARG_NONE, &opt_no_bootloader, "Don't update bootloader", NULL },
{ NULL }
};
static gboolean
-update_initramfs (const char *release,
- const char *deploy_target,
- GCancellable *cancellable,
- GError **error)
+copy_modules (const char *release,
+ GCancellable *cancellable,
+ GError **error)
{
gboolean ret = FALSE;
+ ot_lobj GFile *src_modules_file = NULL;
ot_lobj GFile *dest_modules_parent = NULL;
ot_lobj GFile *dest_modules_file = NULL;
- ot_lfree char *initramfs_name = NULL;
- ot_lobj GFile *initramfs_file = NULL;
- ot_lfree char *last_deploy_path = NULL;
-
+
+ src_modules_file = ot_gfile_from_build_path ("/lib/modules", release, NULL);
dest_modules_file = ot_gfile_from_build_path (opt_ostree_dir, "modules", release, NULL);
dest_modules_parent = g_file_get_parent (dest_modules_file);
if (!ot_gfile_ensure_directory (dest_modules_parent, FALSE, error))
goto out;
- if (!g_file_query_exists (dest_modules_file, NULL))
- {
- ot_lptrarray GPtrArray *cp_args = NULL;
- ot_lobj GFile *src_modules_file = ot_gfile_from_build_path ("/lib/modules", release, NULL);
-
- cp_args = g_ptr_array_new ();
- ot_ptrarray_add_many (cp_args, "cp", "-al", ot_gfile_get_path_cached (src_modules_file),
- ot_gfile_get_path_cached (dest_modules_file), NULL);
- g_ptr_array_add (cp_args, NULL);
- g_print ("Copying kernel modules from %s\n", ot_gfile_get_path_cached (src_modules_file));
- if (!ot_spawn_sync_checked (NULL, (char**)cp_args->pdata, NULL,
- G_SPAWN_SEARCH_PATH,
- NULL, NULL, NULL, NULL, error))
+ if (!g_file_query_exists (dest_modules_file, cancellable))
+ {
+ if (!ot_gio_shutil_cp_al_or_fallback (src_modules_file, dest_modules_file, cancellable, error))
goto out;
}
+ ret = TRUE;
+ out:
+ if (error)
+ g_prefix_error (error, "Error copying kernel modules: ");
+ return ret;
+}
+
+static gboolean
+update_initramfs (const char *release,
+ const char *deploy_target,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gboolean ret = FALSE;
+ ot_lfree char *initramfs_name = NULL;
+ ot_lobj GFile *initramfs_file = NULL;
+ ot_lfree char *last_deploy_path = NULL;
+
initramfs_name = g_strconcat ("initramfs-ostree-", release, ".img", NULL);
initramfs_file = ot_gfile_from_build_path ("/boot", initramfs_name, NULL);
if (!g_file_query_exists (initramfs_file, NULL))
gboolean ret = FALSE;
const char *deploy_target = NULL;
const char *revision = NULL;
+ struct utsname utsname;
+ const char *release;
__attribute__((unused)) GCancellable *cancellable = NULL;
if (!opt_ostree_dir)
if (!do_checkout (self, deploy_target, revision, cancellable, error))
goto out;
- if (!opt_checkout_only)
+ (void) uname (&utsname);
+
+ if (strcmp (utsname.sysname, "Linux") != 0)
{
-
- struct utsname utsname;
- const char *release;
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Unsupported machine %s", utsname.sysname);
+ goto out;
+ }
- (void) uname (&utsname);
+ release = utsname.release;
- if (strcmp (utsname.sysname, "Linux") != 0)
- {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "Unsupported machine %s", utsname.sysname);
- goto out;
- }
-
- release = utsname.release;
-
+ if (!copy_modules (release, cancellable, error))
+ goto out;
+
+ if (!opt_no_initramfs)
+ {
if (!update_initramfs (release, deploy_target, cancellable, error))
goto out;
-
+ }
+
+ if (!opt_no_bootloader)
+ {
if (!update_grub (release, cancellable, error))
goto out;
}